/**
 * <copyright>
 * </copyright>
 *
 * $Id$
 */
package edu.pku.sei.ocl.types.impl;

import java.util.ArrayList;
import java.util.HashMap;

import edu.pku.sei.ocl.types.*;

import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EcoreFactory;

import org.eclipse.emf.ecore.impl.EFactoryImpl;

import org.eclipse.emf.ecore.plugin.EcorePlugin;

/**
 * <!-- begin-user-doc -->
 * An implementation of the model <b>Factory</b>.
 * <!-- end-user-doc -->
 * @generated
 */
public class TypesFactoryImpl extends EFactoryImpl implements TypesFactory {
	/**
	 * Creates the default factory implementation.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public static TypesFactory init() {
		try {
			TypesFactory theTypesFactory = (TypesFactory)EPackage.Registry.INSTANCE.getEFactory("edu.pku.sei.ocl.types"); 
			if (theTypesFactory != null) {
				return theTypesFactory;
			}
		}
		catch (Exception exception) {
			EcorePlugin.INSTANCE.log(exception);
		}
		return new TypesFactoryImpl();
	}

	/**
	 * Creates an instance of the factory.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public TypesFactoryImpl() {
		super();
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public EObject create(EClass eClass) {
		switch (eClass.getClassifierID()) {
			case TypesPackage.OCL_ANY: return createOclAny();
			case TypesPackage.OCL_VOID: return createOclVoid();
			case TypesPackage.OCL_INVALID: return createOclInvalid();
			case TypesPackage.COLLECTION_TYPE: return createCollectionType();
			case TypesPackage.BAG_TYPE: return createBagType();
			case TypesPackage.SET_TYPE: return createSetType();
			case TypesPackage.SEQUENCE_TYPE: return createSequenceType();
			case TypesPackage.ORDERED_SET_TYPE: return createOrderedSetType();
			case TypesPackage.REAL_TYPE: return createRealType();
			case TypesPackage.INTEGER_TYPE: return createIntegerType();
			case TypesPackage.BOOLEAN_TYPE: return createBooleanType();
			case TypesPackage.STRING_TYPE: return createStringType();
			case TypesPackage.UNLIMITED_NATURAL: return createUnlimitedNatural();
			case TypesPackage.TUPLE_TYPE: return createTupleType();
			default:
				throw new IllegalArgumentException("The class '" + eClass.getName() + "' is not a valid classifier");
		}
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public OclAny createOclAny() {
		OclAnyImpl oclAny = new OclAnyImpl();
		return oclAny;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public OclVoid createOclVoid() {
		OclVoidImpl oclVoid = new OclVoidImpl();
		return oclVoid;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public OclInvalid createOclInvalid() {
		OclInvalidImpl oclInvalid = new OclInvalidImpl();
		return oclInvalid;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public CollectionType createCollectionType() {
		CollectionTypeImpl collectionType = new CollectionTypeImpl();
		return collectionType;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public BagType createBagType() {
		BagTypeImpl bagType = new BagTypeImpl();
		return bagType;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public SetType createSetType() {
		SetTypeImpl setType = new SetTypeImpl();
		return setType;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public SequenceType createSequenceType() {
		SequenceTypeImpl sequenceType = new SequenceTypeImpl();
		return sequenceType;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public OrderedSetType createOrderedSetType() {
		OrderedSetTypeImpl orderedSetType = new OrderedSetTypeImpl();
		return orderedSetType;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public RealType createRealType() {
		RealTypeImpl realType = new RealTypeImpl();
		return realType;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public IntegerType createIntegerType() {
		IntegerTypeImpl integerType = new IntegerTypeImpl();
		return integerType;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public BooleanType createBooleanType() {
		BooleanTypeImpl booleanType = new BooleanTypeImpl();
		return booleanType;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public StringType createStringType() {
		StringTypeImpl stringType = new StringTypeImpl();
		return stringType;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public UnlimitedNatural createUnlimitedNatural() {
		UnlimitedNaturalImpl unlimitedNatural = new UnlimitedNaturalImpl();
		return unlimitedNatural;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public TupleType createTupleType() {
		TupleTypeImpl tupleType = new TupleTypeImpl();
		return tupleType;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public TypesPackage getTypesPackage() {
		return (TypesPackage)getEPackage();
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @deprecated
	 * @generated
	 */
	@Deprecated
	public static TypesPackage getPackage() {
		return TypesPackage.eINSTANCE;
	}

	private HashMap<EClassifier,CollectionType> collectionTypeCache = new HashMap<EClassifier,CollectionType>();
	
	public CollectionType createCollectionType(EClassifier elementType){
		CollectionType ec = collectionTypeCache.get(elementType);
		
		if(ec==null) {
			ec = this.createCollectionType();
			ec.setElementType(elementType);
			collectionTypeCache.put(elementType, ec);
		}
		return ec;
	}
	
	private HashMap<EClassifier,SetType> setTypeCache = new HashMap<EClassifier,SetType>();
	
	public SetType createSetType(EClassifier elementType){
		SetType ec = setTypeCache.get(elementType);
		
		if(ec==null) {
			ec = this.createSetType();
			ec.setElementType(elementType);
			setTypeCache.put(elementType, ec);
		}
		return ec;
	}
	
	private HashMap<EClassifier,BagType> bagTypeCache = new HashMap<EClassifier,BagType>();
	
	public BagType createBagType(EClassifier elementType){
		BagType ec = bagTypeCache.get(elementType);
		
		if(ec==null) {
			ec = this.createBagType();
			ec.setElementType(elementType);
			bagTypeCache.put(elementType, ec);
		}
		return ec;
	}
	
	private HashMap<EClassifier,SequenceType> sequenceTypeCache = new HashMap<EClassifier,SequenceType>();
	
	public SequenceType createSequenceType(EClassifier elementType){
		SequenceType ec = sequenceTypeCache.get(elementType);
		
		if(ec==null) {
			ec = this.createSequenceType();
			ec.setElementType(elementType);
			sequenceTypeCache.put(elementType, ec);
		}
		return ec;
	}
	
	private HashMap<EClassifier,OrderedSetType> orderedSetTypeCache = new HashMap<EClassifier,OrderedSetType>();
	
	public OrderedSetType createOrderedSetType(EClassifier elementType){
		OrderedSetType ec = orderedSetTypeCache.get(elementType);
		
		if(ec==null) {
			ec = this.createOrderedSetType();
			ec.setElementType(elementType);
			orderedSetTypeCache.put(elementType, ec);
		}
		return ec;
	}

	private ArrayList<TupleType> tupleTypeCache = new ArrayList<TupleType>();
	
	@Override
	public EClassifier createTupleType(String[] keyNames,
			EClassifier[] valueOclTypes) {
		// TODO Auto-generated method stub
		for(TupleType tt : tupleTypeCache){
			if(tt.equals(keyNames,valueOclTypes))
				return tt;
		}
		TupleType result = this.createTupleType();
		
		int i;
		for(i=0;i<keyNames.length;i++){
			EAttribute ea = EcoreFactory.eINSTANCE.createEAttribute();
			ea.setName(keyNames[i]);
			ea.setEType(valueOclTypes[i]);
			result.getProperties().add(ea);
		}
		
		return result;
	}
	
} //TypesFactoryImpl
